/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../helper_objs/head.h"
#include "../msg_fast/head.h"
#include "../config/head.h"
#include "../impl/head.h"
#include "../macro/head.h"
#include "../msg/head.h"
#include "task.h"

namespace xos_http
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static task::ITEM_DATA xos_item_data;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    task::task()
    {
        init_data();
    }

    task::~task()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int task::get_xos_item_data( ITEM_DATA*& item_ptr )
    {
        int ret = 0;
        xos_item_data.set_container( mgr::container() );
        item_ptr = &xos_item_data;
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int task::set_connect( http::i_connect * pConnect )
    {
        int ret = 0;
        m_pResponse->set_connect( pConnect );
        m_pRequest->set_connect( pConnect );
        m_pConnect = (connection*)pConnect;
        prop()->set_str_prop( "connection", get_connect()->prop(), false );
        return ret;
    }

    http::i_response * task::http_response()
    {
        return m_pResponse;
    }

    http::i_request * task::http_request()
    {
        return m_pRequest;
    }

    http::i_connect * task::get_connect()
    {
        return m_pConnect;
    }

    const char * task::super_variable( const char * lpszName )
    {
        const char * pRet = 0;
        if( !pRet )
        {
            xos_box::i_str_property * pProp = prop();
            std::string name = lpszName;
            std::string sub;
            bool bHasDot = false;
            while( pProp )
            {
                size_t tPos = name.find_first_of( '.' );
                if( tPos != std::string::npos )
                {
                    sub = name.substr( 0, tPos );
                    name = name.substr( tPos + 1 );
                    bHasDot = true;
                }
                else if( bHasDot )
                {
                    sub = name;
                    break;
                }
                else
                {
                    break;
                }
                if( bHasDot )
                {
                    pProp = pProp->str_prop( sub.c_str() );
                }
            }
            if( bHasDot && pProp )
            {
                pRet = pProp->str( sub.c_str() );
            }
        }
        if( !pRet )
        {
            pRet = values()->str( lpszName );
        }
        if( !pRet )
        {
            pRet = http_request()->tags()->str( lpszName );
        }
        if( !pRet )
        {
            pRet = http_request()->params()->str( lpszName );
        }
        if( !pRet )
        {
            pRet = http_response()->tags()->str( lpszName );
        }
        if( !pRet )
        {
            pRet = get_connect()->prop()->str( lpszName );
        }
        if( !pRet )
        {
            pRet = "";
        }
        return pRet;
    }

    xos_box::i_str_property * task::values()
    {
        return m_pValues;
    }

    xos_box::i_str_property * task::prop()
    {
        return m_pProperty;
    }

    int task::call( const char * lpszUri )
    {
        int ret = 0;
        // 保存现场
        {
            push();
        }
        // 发起调用
        {
            xos_box::i_msg * pMsg = mgr::container()->box()->msg();
            m_uri_list.push_back( lpszUri );
            reset_uri_iters();
            pMsg->set_void( 0, this );
            m_eState = STATE_PROC_TASK;
            get_connect()->fast_notify()->notify( pMsg, FAST_JOB );
        }
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int task::get_task_info_from_http()
    {
        int ret = 0;
        connection * pListenCon = m_pConnect->m_pListenConnect;
        config * pConfig = config::get();
        {
            xos_box::i_str_property * pTags = m_pRequest->tags();
            m_host_name = pTags->str( xos_http_protocol::HTTP_HOST );
            m_host_port = pTags->str( xos_http_protocol::HTTP_PORT );
            m_host_ip = m_pConnect->get_net_connect()->local_ip();
        }
        {
            m_pPort = pListenCon->m_pPort;
            m_pHost = (host *)m_pPort->m_pProp->obj( m_host_name.c_str() );
            if( !m_pHost )
            {
                m_pHost = (host *)m_pPort->m_pProp->obj( pConfig->m_default_host.c_str() );
            }
            m_pRoot = (path *)m_pHost->m_pProp->obj( pConfig->m_root.c_str() );
            m_pSsl = (path *)m_pHost->m_pProp->obj( pConfig->m_ssl.c_str() );
        }
        return ret;
    }

    int task::reset_filter_iters()
    {
        int ret = 0;
        m_filter_list_riter = m_filter_list.rbegin();
        m_filter_list_iter = m_filter_list.begin();
        return ret;
    }

    int task::reset_uri_iters()
    {
        int ret = 0;
        m_uri_list_iter = m_uri_list.begin();
        return ret;
    }

    int task::push()
    {
        int ret = 0;
        stack::T * pStack = 0;
        xos_stl::init_pool_item( pStack );
        pStack->push( this );
        m_pCallStackList->push_front( pStack );
        pStack = 0;
        return ret;
    }

    int task::pop()
    {
        int ret = 0;
        stack * pStack = (stack *)m_pCallStackList->front( 0 );
        if( pStack )
        {
            m_pCallStackList->pop_front();
            pStack->pop();
            xos_stl::release_interface( pStack );
        }
        else
        {
            ret = 1;
        }
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    int task::init_data()
    {
        int ret = 0;

        reset_filter_iters();

        m_eState = STATE_PREPARE;

        m_pConnect = 0;
        m_pResponse = 0;
        m_pRequest = 0;
        m_host_name = "";
        m_host_port = "";
        m_host_ip = "";

        m_pCallStackList = 0;
        m_pServlet = 0;
        m_pModule = 0;

        m_pPort = 0;
        m_pHost = 0;
        m_pRoot = 0;
        m_pPath = 0;
        m_pSsl = 0;

        m_full_download_gz_file = "";
        m_full_download_file = "";
        m_full_uri = "";
        m_uri = "";
        m_name = "";
        m_ext = "";

        m_pDownloadFile = 0;

        m_pProperty = 0;
        m_pValues = 0;

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    int task::init()
    {
        int ret = 0;
        if( 0 == ret )
        {
            response::T * pT = 0;
            xos_stl::init_pool_item( pT );
            pT->m_pTask = this;
            m_pResponse = pT;
        }
        if( 0 == ret )
        {
            request::T * pT = 0;
            xos_stl::init_pool_item( pT );
            pT->m_pTask = this;
            m_pRequest = pT;
        }
        if( 0 == ret )
        {
            m_pProperty = mgr::container()->box()->get_str_prop();
            m_pValues = mgr::container()->box()->get_str_prop();
            prop()->set_str_prop( "response", http_response()->prop(), false);
            prop()->set_str_prop( "request", http_request()->prop(), false );
            prop()->set_str_prop( "task", m_pProperty, false );
        }
        if( 0 == ret )
        {
            m_pCallStackList = mgr::container()->box()->list();
        }
        return ret;
    }

    int task::term()
    {
        int ret = 0;
        xos_stl::release_interface( m_pCallStackList );
        xos_stl::release_interface( m_pProperty );
        xos_stl::release_interface( m_pValues );
        xos_stl::release_interface( m_pResponse );
        xos_stl::release_interface( m_pRequest );
        {
            http_proc obj;
            obj.free_filters( m_filter_list );
        }
        xos_stl::release_interface( m_pServlet );
        xos_stl::release_ref( m_pModule );
        m_uri_list.clear();
        init_data();
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

} // xos_http
